<!DOCTYPE html>
<html lang="en">

	<head>
		<meta charset="UTF-8">
		<title>Document</title>
		<style>
			* {
				margin: 0;
				padding: 0;
			}
			#tab {
			}
			#tab td{
				border: solid 1px black;
				padding: 10px;
			}
			.cover {
				background: black;
			}
			.food {
				background: green;
			}
		</style>
	</head>
	<script src="common.js" type="text/javascript" charset="utf-8"></script>
	<body>
		<table id="tab"></table>
	</body>
	<script>
		Array.prototype.baohan = function(obj){
			if(typeof obj == "object") {
				for(var i=0; i<this.length; i++) {
					var isSame = true;
					for(var attr in this[i]){
						if(this[i][attr] != obj[attr]) {
							isSame = false;
							break;
						}
					}
					if(isSame) {
						return true;
					}
				}
				return false;
			} else {
				
			}
		}
	
		for(var i=0; i<20; i++) {
			var tr = document.createElement("tr");
			for(var j=0; j<20; j++) {
				var td = document.createElement("td");
				tr.appendChild(td);
			}
			tab.appendChild(tr);
		}
		
		var game = new GameEngine();
		game.start();
		
		function GameEngine(){
			var self = this;
			this.food = null;
			this.snk = null;
			this.start = function(){
				document.onkeydown = function(e){
					e = e || event;
					var code = e.keyCode || e.which;
					switch(code) {
						case 38 : {
							if(self.snk.direction == 2) return;
							self.snk.direction = 0; break;
						}
						case 39 : {
							if(self.snk.direction == 3) return;
							self.snk.direction = 1; break;
						}
		 				case 40 : {
		 					if(self.snk.direction == 0) return;
		 					self.snk.direction = 2; break;
		 				}
						case 37 : {
							if(self.snk.direction == 1) return;
							self.snk.direction = 3; break;
						}
					}
				}
				//随机生产蛇
				this.snk = new Snake().init();
				//随机产生一个食物
				this.food = this.createFood();
				//开始移动				
				this.snk.run();
			}
			this.createFood = function(){
				var obj = null;
				do {
					obj = new Food(this.snk);
				} while(!this.checkFood(obj))
				tab.children[obj.getX()].children[obj.getY()].className = "food";
				return obj;
			}
			this.checkFood = function(obj){
				var flag = true;
				for(var i=0; i<this.snk.body.length; i++) {
					if(this.snk.body[i].x == obj.getX() && this.snk.body[i].y == obj.getY()) {
						flag = false;
					}
				}
				return flag;
			}
			this.notify = function(){
				this.food = this.createFood();
			}
		}
		
		function Food(snk){
			this.coord = {x:randomInt(0,19), y:randomInt(0,19)};
			this.getX = function(){
				return this.coord.x;				
			}
			this.getY = function(){
				return this.coord.y;
			}
		}
		
		
		
		function Snake(){
			var self = this;
			this.init = function(){
				this.body = [{x:randomInt(0,19), y:randomInt(0,19)}];
				this.direction = randomInt(0,3);
				this.speed = 400;
				this.refresh();
				this.print();
				return this;
			}
			this.refresh = function(){
				this.head = this.body[0];
				this.last = this.body[this.body.length-1];
			}
			this.print = function(){
				for(var i=0; i<this.body.length; i++) {
					var cd = this.body[i];
					tab.children[cd.x].children[cd.y].className = "cover";
				}
			}
			this.run = function(){
				var next = null;
				//计算下一步的位置
				switch(this.direction) {
					case 0 : next = {x:this.head.x-1, y:this.head.y}; break; //↑
					case 1 : next = {x:this.head.x, y:this.head.y+1}; break; //→
					case 2 : next = {x:this.head.x+1, y:this.head.y}; break; //↓
					case 3 : next = {x:this.head.x, y:this.head.y-1}; break; //←
				}
				
				//是否撞到自己的尾巴
				if(this.body.baohan(next)) {
					alert("咬尾自尽！");
					throw Error("GAME OVER");
				}
				
				//下一个位置出界?
				if(next.x > 19 || next.x < 0 || next.y > 19 || next.y < 0) {
					alert("游戏结束，撞死了");
					throw Error("GAME OVER！");
				}
				
				//下一个位置有食物？
				if((next.x == game.food.getX() && next.y == game.food.getY())) {
					this.eat(next);
				} else {
					this.squirm(next);
				}
				
				//递归移动
				setTimeout(function(){
					self.run();
				},this.speed);
			}
			this.eat = function(food){
				//按方向增加头部				
				this.add(food);
				this.speed = Math.max(this.speed-20, 200);
				game.notify();
			}
			this.squirm = function(next){
				//按方向增加头部				
				this.add(next);
				//去掉尾部
				this.remove();	
			}
			this.remove = function(){
				this.body.pop();
				//先删除尾部
				tab.children[this.last.x].children[this.last.y].className = "";
				//再刷新头尾指针(尾部指针前移)
				this.refresh();
			}
			this.add = function(next){
				this.body.unshift(next);
				//先刷新头尾指针
				this.refresh();
				//再删除头部()
				tab.children[this.head.x].children[this.head.y].className = "cover";
			}
		}
	</script>

</html>